home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.4) """distutils.command.build_ext Implements the Distutils 'build_ext' command, for building extension modules (currently limited to C extensions, should accommodate C++ extensions ASAP).""" __revision__ = '$Id: build_ext.py,v 1.98 2004/11/10 22:23:15 loewis Exp $' import sys import os import string import re from types import * from distutils.core import Command from distutils.errors import * from distutils.sysconfig import customize_compiler, get_python_version from distutils.dep_util import newer_group from distutils.extension import Extension from distutils import log extension_name_re = re.compile('^[a-zA-Z_][a-zA-Z_0-9]*(\\.[a-zA-Z_][a-zA-Z_0-9]*)*$') def show_compilers(): show_compilers = show_compilers import distutils.ccompiler show_compilers() class build_ext(Command): description = 'build C/C++ extensions (compile/link to build directory)' sep_by = " (separated by '%s')" % os.pathsep user_options = [ ('build-lib=', 'b', 'directory for compiled extension modules'), ('build-temp=', 't', 'directory for temporary files (build by-products)'), ('inplace', 'i', 'ignore build-lib and put compiled extensions into the source ' + 'directory alongside your pure Python modules'), ('include-dirs=', 'I', 'list of directories to search for header files' + sep_by), ('define=', 'D', 'C preprocessor macros to define'), ('undef=', 'U', 'C preprocessor macros to undefine'), ('libraries=', 'l', 'external C libraries to link with'), ('library-dirs=', 'L', 'directories to search for external C libraries' + sep_by), ('rpath=', 'R', 'directories to search for shared C libraries at runtime'), ('link-objects=', 'O', 'extra explicit link objects to include in the link'), ('debug', 'g', 'compile/link with debugging information'), ('force', 'f', 'forcibly build everything (ignore file timestamps)'), ('compiler=', 'c', 'specify the compiler type'), ('swig-cpp', None, 'make SWIG create C++ files (default is C)'), ('swig-opts=', None, 'list of SWIG command line options'), ('swig=', None, 'path to the SWIG executable')] boolean_options = [ 'inplace', 'debug', 'force', 'swig-cpp'] help_options = [ ('help-compiler', None, 'list available compilers', show_compilers)] def initialize_options(self): self.extensions = None self.build_lib = None self.build_temp = None self.inplace = 0 self.package = None self.include_dirs = None self.define = None self.undef = None self.libraries = None self.library_dirs = None self.rpath = None self.link_objects = None self.debug = None self.force = None self.compiler = None self.swig = None self.swig_cpp = None self.swig_opts = None def finalize_options(self): sysconfig = sysconfig import distutils self.set_undefined_options('build', ('build_lib', 'build_lib'), ('build_temp', 'build_temp'), ('compiler', 'compiler'), ('debug', 'debug'), ('force', 'force')) if self.package is None: self.package = self.distribution.ext_package self.extensions = self.distribution.ext_modules py_include = sysconfig.get_python_inc() plat_py_include = sysconfig.get_python_inc(plat_specific = 1) if self.include_dirs is None: if not self.distribution.include_dirs: pass self.include_dirs = [] if type(self.include_dirs) is StringType: self.include_dirs = string.split(self.include_dirs, os.pathsep) self.include_dirs.append(py_include) if plat_py_include != py_include: self.include_dirs.append(plat_py_include) if type(self.libraries) is StringType: self.libraries = [ self.libraries] if self.libraries is None: self.libraries = [] if self.library_dirs is None: self.library_dirs = [] elif type(self.library_dirs) is StringType: self.library_dirs = string.split(self.library_dirs, os.pathsep) if self.rpath is None: self.rpath = [] elif type(self.rpath) is StringType: self.rpath = string.split(self.rpath, os.pathsep) if os.name == 'nt': self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) if self.debug: self.build_temp = os.path.join(self.build_temp, 'Debug') else: self.build_temp = os.path.join(self.build_temp, 'Release') self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild')) if os.name == 'os2': self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config')) if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos': if string.find(sys.executable, sys.exec_prefix) != -1: self.library_dirs.append(os.path.join(sys.prefix, 'lib', 'python' + get_python_version(), 'config')) else: self.library_dirs.append('.') if self.define: defines = string.split(self.define, ',') self.define = map((lambda symbol: (symbol, '1')), defines) if self.undef: self.undef = string.split(self.undef, ',') if self.swig_opts is None: self.swig_opts = [] else: self.swig_opts = self.swig_opts.split(' ') def run(self): new_compiler = new_compiler import distutils.ccompiler if not self.extensions: return None if self.distribution.has_c_libraries(): build_clib = self.get_finalized_command('build_clib') if not build_clib.get_library_names(): pass self.libraries.extend([]) self.library_dirs.append(build_clib.build_clib) self.compiler = new_compiler(compiler = self.compiler, verbose = self.verbose, dry_run = self.dry_run, force = self.force) customize_compiler(self.compiler) if self.include_dirs is not None: self.compiler.set_include_dirs(self.include_dirs) if self.define is not None: for name, value in self.define: self.compiler.define_macro(name, value) if self.undef is not None: for macro in self.undef: self.compiler.undefine_macro(macro) if self.libraries is not None: self.compiler.set_libraries(self.libraries) if self.library_dirs is not None: self.compiler.set_library_dirs(self.library_dirs) if self.rpath is not None: self.compiler.set_runtime_library_dirs(self.rpath) if self.link_objects is not None: self.compiler.set_link_objects(self.link_objects) self.build_extensions() def check_extensions_list(self, extensions): """Ensure that the list of extensions (presumably provided as a command option 'extensions') is valid, i.e. it is a list of Extension objects. We also support the old-style list of 2-tuples, where the tuples are (ext_name, build_info), which are converted to Extension instances here. Raise DistutilsSetupError if the structure is invalid anywhere; just returns otherwise. """ if type(extensions) is not ListType: raise DistutilsSetupError, "'ext_modules' option must be a list of Extension instances" for i in range(len(extensions)): ext = extensions[i] if isinstance(ext, Extension): continue (ext_name, build_info) = ext log.warn("old-style (ext_name, build_info) tuple found in ext_modules for extension '%s'-- please convert to Extension instance" % ext_name) if type(ext) is not TupleType and len(ext) != 2: raise DistutilsSetupError, "each element of 'ext_modules' option must be an Extension instance or 2-tuple" if not type(ext_name) is StringType and extension_name_re.match(ext_name): raise DistutilsSetupError, "first element of each tuple in 'ext_modules' must be the extension name (a string)" if type(build_info) is not DictionaryType: raise DistutilsSetupError, "second element of each tuple in 'ext_modules' must be a dictionary (build info)" ext = Extension(ext_name, build_info['sources']) for key in ('include_dirs', 'library_dirs', 'libraries', 'extra_objects', 'extra_compile_args', 'extra_link_args'): val = build_info.get(key) if val is not None: setattr(ext, key, val) continue ext.runtime_library_dirs = build_info.get('rpath') if build_info.has_key('def_file'): log.warn("'def_file' element of build info dict no longer supported") macros = build_info.get('macros') if macros: ext.define_macros = [] ext.undef_macros = [] for macro in macros: if type(macro) is TupleType: if len(macro) <= len(macro): pass elif not len(macro) <= 2: raise DistutilsSetupError, "'macros' element of build info dict must be 1- or 2-tuple" if len(macro) == 1: ext.undef_macros.append(macro[0]) continue 1 if len(macro) == 2: ext.define_macros.append(macro) continue extensions[i] = ext def get_source_files(self): self.check_extensions_list(self.extensions) filenames = [] for ext in self.extensions: filenames.extend(ext.sources) return filenames def get_outputs(self): self.check_extensions_list(self.extensions) outputs = [] for ext in self.extensions: fullname = self.get_ext_fullname(ext.name) outputs.append(os.path.join(self.build_lib, self.get_ext_filename(fullname))) return outputs def build_extensions(self): self.check_extensions_list(self.extensions) for ext in self.extensions: self.build_extension(ext) def build_extension(self, ext): sources = ext.sources if sources is None or type(sources) not in (ListType, TupleType): raise DistutilsSetupError, ("in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + 'a list of source filenames') % ext.name sources = list(sources) fullname = self.get_ext_fullname(ext.name) if self.inplace: modpath = string.split(fullname, '.') package = string.join(modpath[0:-1], '.') base = modpath[-1] build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(package) ext_filename = os.path.join(package_dir, self.get_ext_filename(base)) else: ext_filename = os.path.join(self.build_lib, self.get_ext_filename(fullname)) depends = sources + ext.depends if not self.force or newer_group(depends, ext_filename, 'newer'): log.debug("skipping '%s' extension (up-to-date)", ext.name) return None else: log.info("building '%s' extension", ext.name) sources = self.swig_sources(sources, ext) if not ext.extra_compile_args: pass extra_args = [] macros = ext.define_macros[:] for undef in ext.undef_macros: macros.append((undef,)) objects = self.compiler.compile(sources, output_dir = self.build_temp, macros = macros, include_dirs = ext.include_dirs, debug = self.debug, extra_postargs = extra_args, depends = ext.depends) self._built_objects = objects[:] if ext.extra_objects: objects.extend(ext.extra_objects) if not ext.extra_link_args: pass extra_args = [] if not ext.language: pass language = self.compiler.detect_language(sources) self.compiler.link_shared_object(objects, ext_filename, libraries = self.get_libraries(ext), library_dirs = ext.library_dirs, runtime_library_dirs = ext.runtime_library_dirs, extra_postargs = extra_args, export_symbols = self.get_export_symbols(ext), debug = self.debug, build_temp = self.build_temp, target_lang = language) def swig_sources(self, sources, extension): """Walk the list of source files in 'sources', looking for SWIG interface (.i) files. Run SWIG on all that are found, and return a modified 'sources' list with SWIG source files replaced by the generated C (or C++) files. """ new_sources = [] swig_sources = [] swig_targets = { } if self.swig_cpp: log.warn('--swig-cpp is deprecated - use --swig-opts=-c++') if self.swig_cpp or '-c++' in self.swig_opts: target_ext = '.cpp' else: target_ext = '.c' for source in sources: (base, ext) = os.path.splitext(source) if ext == '.i': new_sources.append(base + '_wrap' + target_ext) swig_sources.append(source) swig_targets[source] = new_sources[-1] continue new_sources.append(source) if not swig_sources: return new_sources if not self.swig: pass swig = self.find_swig() swig_cmd = [ swig, '-python'] swig_cmd.extend(self.swig_opts) if self.swig_cpp: swig_cmd.append('-c++') if not self.swig_opts: for o in extension.swig_opts: swig_cmd.append(o) for source in swig_sources: target = swig_targets[source] log.info('swigging %s to %s', source, target) self.spawn(swig_cmd + [ '-o', target, source]) return new_sources def find_swig(self): '''Return the name of the SWIG executable. On Unix, this is just "swig" -- it should be in the PATH. Tries a bit harder on Windows. ''' if os.name == 'posix': return 'swig' elif os.name == 'nt': for vers in ('1.3', '1.2', '1.1'): fn = os.path.join('c:\\swig%s' % vers, 'swig.exe') if os.path.isfile(fn): return fn continue else: return 'swig.exe' elif os.name == 'os2': return 'swig.exe' else: raise DistutilsPlatformError, "I don't know how to find (much less run) SWIG on platform '%s'" % os.name def get_ext_fullname(self, ext_name): if self.package is None: return ext_name else: return self.package + '.' + ext_name def get_ext_filename(self, ext_name): '''Convert the name of an extension (eg. "foo.bar") into the name of the file from which it will be loaded (eg. "foo/bar.so", or "foo\\bar.pyd"). ''' get_config_var = get_config_var import distutils.sysconfig ext_path = string.split(ext_name, '.') if os.name == 'os2': ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] so_ext = get_config_var('SO') if os.name == 'nt' and self.debug: return apply(os.path.join, ext_path) + '_d' + so_ext return apply(os.path.join, ext_path) + so_ext def get_export_symbols(self, ext): '''Return the list of symbols that a shared extension has to export. This either uses \'ext.export_symbols\' or, if it\'s not provided, "init" + module_name. Only relevant on Windows, where the .pyd file (DLL) must export the module "init" function. ''' initfunc_name = 'init' + string.split(ext.name, '.')[-1] if initfunc_name not in ext.export_symbols: ext.export_symbols.append(initfunc_name) return ext.export_symbols def get_libraries(self, ext): """Return the list of libraries to link against when building a shared extension. On most platforms, this is just 'ext.libraries'; on Windows and OS/2, we add the Python library (eg. python20.dll). """ if sys.platform == 'win32': MSVCCompiler = MSVCCompiler import distutils.msvccompiler if not isinstance(self.compiler, MSVCCompiler): template = 'python%d%d' if self.debug: template = template + '_d' pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) return ext.libraries + [ pythonlib] else: return ext.libraries elif sys.platform == 'os2emx': template = 'python%d%d' pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) return ext.libraries + [ pythonlib] elif sys.platform[:6] == 'cygwin': template = 'python%d.%d' pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) return ext.libraries + [ pythonlib] elif sys.platform[:6] == 'atheos': sysconfig = sysconfig import distutils template = 'python%d.%d' pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) extra = [] for lib in sysconfig.get_config_var('SHLIBS').split(): if lib.startswith('-l'): extra.append(lib[2:]) continue extra.append(lib) return ext.libraries + [ pythonlib, 'm'] + extra else: return ext.libraries